# 导入必要的库
import joblib
from sklearn.ensemble import VotingClassifier

from Tools import readbunchobj
from joblib import dump
from sklearn.model_selection import cross_val_score
from Tools import metrics_result

# 加载保存的模型和TfidfVectorizer
log_clf = joblib.load('LogisticRegression_model.joblib')
bayes_clf = joblib.load('Bayes_model.joblib')
rf_clf = joblib.load('RF_model.joblib')

log_clf.n_jobs = -1
# 对于随机森林分类器，设置n_jobs参数
rf_clf.n_jobs = -1  # 启用所有可用的CPU核心

vectorizer = joblib.load('../vectorizer.joblib')

# 导入训练集
train_path = "../train_word_bag/tf_idf_space.dat"
train_set = readbunchobj(train_path)

# 导入测试集
testpath = "../test_word_bag/test_tf_idf_space.dat"
test_set = readbunchobj(testpath)

print("使用交叉验证计算每个模型的平均精度得分：\n")
# 使用交叉验证计算每个模型的平均精度得分
precision_scores = {}
for name, model in [('bayes', bayes_clf), ('log', log_clf),('rf', rf_clf)]:
    score = cross_val_score(model, train_set.tdm, train_set.label, cv=5, scoring='accuracy', n_jobs=-1)
    precision_scores[name] = score.mean()

# 根据交叉验证的平均精度得分分配权重
total_cv_precision = sum(precision_scores.values())
weights_cv = {name: score / total_cv_precision for name, score in precision_scores.items()}

# 打印基于交叉验证的权重
print(f"朴素贝叶斯模型的权重: {weights_cv['bayes']}")
print(f"逻辑回归模型的权重: {weights_cv['log']}")
print(f"随机森林模型的权重: {weights_cv['rf']}")

# 使用交叉验证权重的加权投票集成模型
ensemble_clf_weighted_cv = VotingClassifier(
    estimators =
    [
        ('bayes', bayes_clf),
        ('log', log_clf),
        ('rf', rf_clf)
    ],
    voting = 'soft',
    weights = [weights_cv['bayes'], weights_cv['log'], weights_cv['rf']]
    )


# 训练集成模型
print("开始训练集成模型...")
ensemble_clf_weighted_cv.fit(train_set.tdm, train_set.label)
print("集成模型训练完成。")

# 保存集成模型到文件中
dump(ensemble_clf_weighted_cv, 'EL_model_cv.joblib')
print("集成模型已保存!!!")

# 使用集成模型进行预测
print("USE: 集成模型 预测分类结果")
ensemble_predicted_cv = ensemble_clf_weighted_cv.predict(test_set.tdm)
ensemble_total_cv = len(ensemble_predicted_cv)
print("结束")

# 计算错误率、分类精度
print("\n集成模型（基于交叉验证权重）：")
metrics_result(test_set.label, ensemble_predicted_cv, ensemble_total_cv)
